#ifndef __FAT_H
#define __FAT_H

#include "vfs.h"
#include "ata.h"
#include "fdc.h"

#define FAT_ATTR_READ_ONLY		0x01
#define FAT_ATTR_HIDDEN			0x02
#define FAT_ATTR_SYSTEM			0x04
#define FAT_ATTR_VOLUME_ID		0x08
#define FAT_ATTR_DIRECTORY		0x10
#define FAT_ATTR_ARCHIVE		0x20
#define FAT_ATTR_LONG_NAME		FAT_ATTR_READ_ONLY | FAT_ATTR_HIDDEN | FAT_ATTR_SYSTEM | FAT_ATTR_VOLUME_ID

typedef struct fat_extBS_32
{
	//extended fat32 stuff
	u32int		table_size_32;
	u16int		extended_flags;
	u16int		fat_version;
	u32int		root_cluster;
	u16int		fat_info;
	u16int		backup_BS_sector;
	u8int 		reserved_0[12];
	u8int		drive_number;
	u8int 		reserved_1;
	u8int		boot_signature;
	u32int 		volume_id;
	u8int		volume_label[11];
	u8int		fat_type_label[8];

}__attribute__((packed)) fat_extBS_32_t;

typedef struct fat_extBS_16
{
	//extended fat12 and fat16 stuff
	u8int		bios_drive_num;
	u8int		reserved1;
	u8int		boot_signature;
	u32int		volume_id;
	u8int		volume_label[11];
	u8int		fat_type_label[8];
	
}__attribute__((packed)) fat_extBS_16_t;

typedef struct fat_BS
{
	u8int 		bootjmp[3];
	u8int 		oem_name[8];
	u16int 	bytes_per_sector;
	u8int		sectors_per_cluster;
	u16int		reserved_sector_count;
	u8int		table_count;
	u16int		root_entry_count;
	u16int		total_sectors_16;
	u8int		media_type;
	u16int		table_size_16;
	u16int		sectors_per_track;
	u16int		head_side_count;
	u32int 		hidden_sector_count;
	u32int 		total_sectors_32;
	
	//this will be cast to it's specific type once the driver actually knows what type of FAT this is.
	u8int		extended_section[54];
	
}__attribute__((packed)) fat_BS_t;

//describes a single file entry in a fat table
typedef struct fat_entry
{
	//from the actual file on the disk
	s8int name[12];
	s8int long_name[128];
	u8int has_long_name;
   u8int attr;
   u16int time;
   u16int date;
   u32int cluster;
   u32int size; 
	u8int exists;

	//	information to help us organize the entries
	u32int inode;		//helps to match this entry to a node in the virtual file system
	fs_node_t *device_node;	
	u8int fat_type;

	struct fat_entry *parent;
	struct fat_entry *first_child;
	struct fat_entry *next_sibling;
 
}__attribute__((packed)) fat_entry_t;

typedef struct fat_file_handle
{
	fs_node_t *node;			//a pointer to the filesystem node that this handle is for
	fat_entry_t *entry;		//the coorisponding entry on the table

	struct fat_file_handle *next;	//the next file handle in the list (a linked list)

}fat_file_handle_t;

s32int fat_mount(fs_node_t *root_node, u8int *device_path);

s32int fat_parse_directory(fat_entry_t *entry, fs_node_t *node);

fat_file_handle_t *fat_get_handle(fs_node_t *node, u32int create);
s32int fat_remove_handle(fat_file_handle_t *handle);
s32int fat_add_handle(fat_file_handle_t *handle);

s32int fat_open(fs_node_t *node);
s32int fat_close(fs_node_t *node);
s32int fat_read(fs_node_t *node, u32int offset, u32int size, u8int *buffer);
s32int fat_write(fs_node_t *node, u32int offset, u32int size, u8int *buffer);
s32int fat_scan(fs_node_t* node);

#endif
